import * as Cesium from 'cesium'
import * as turf from '@turf/turf' // Turf.js主要用实现在网页端来空间几何对象关系的计算,点、线、面之间包含、相交等一系统运算。

/*
  使用说明：
    1. 使用行政区域划分的功能服务时需要添加 行政区域划分的图层服务
      this.imageryProvider = addDivisionImageryProvider(viewer)

      ******************************************************
      注意：使用行政区域划分的时候需要将地理深度监听设置为false
      viewer.scene.globe.depthTestAgainstTerrain = false
      *******************************************************

    2. 进行行政区域划分方法  drawDivisionArea(viewer, imageryProvider, options)
        参数说明：
          1. viewer  cesium 基础组件
          2. imageryProvider  调用addDivisionImageryProvider方法返回的图层实例
          3. options 相关配置
            1) point 查询点的位置坐标 世界坐标系，可以通过 lnglatToCartesian 方法进行转换
            2) color 绘制区域的颜色
            3）success 绘制成功的回调
      注意：
        drawDivisionArea 绘制行政区域返回的方法返回的为entity实例
        如果需要删除则 调用 viewer.entities.remove(entity)
        该函数返回的是 entities 的数组，删除时需要遍历删除

    3. drawRangeDivisionArea(viewer, options) 进行范围行政区域划分
        参数说明：
        1. viewer  cesium 基础组件
        2. options 相关配置
          1. center 圆的中心点，世界坐标系
          2. distance  圆的半径 ，单位千米
          3. circleColor  圆的绘制的颜色
          4. allStreetPickeFeaturesData  所有的街道区域地图数组元信息，通过调用 index.vue中的 getStreetMapFeatures 方法获取所有的街道信息
        注意：
          drawRangeDivisionArea 绘制行政区域返回的方法返回的为entity实例
          如果需要删除则 调用 viewer.entities.remove(entity)
          该函数返回的是 entities 的数组，删除时需要遍历删除
 */

// 行政区域划分的图层服务地址   德清县
const divisionImageryProviderUrl = 'http://47.110.136.28//arcgisrest/xczlcunzhenjiewhite-20191126-arcgisrest/9a9ee64f-a77e-4311-a363-26b9a515a747'
// 查询图层服务的图层id   3：街道   2:镇
const pickFeaturesLayerId = 2
const outlineWidth = 4

// 添加行政区域划分的图层   进行区域划分前需要添加该图层
function addDivisionImageryProvider (viewer) {
  const imageryProvider = new Cesium.ArcGisMapServerImageryProvider({
    url: divisionImageryProviderUrl
  })
  // 获取在地球上渲染的图像图层的集合。
  const imageryLayers = viewer.imageryLayers
  // 显示来自单个图像提供者的平铺图像数据的图像层在 Globe 上。
  const arcgisImageryLayer = new Cesium.ImageryLayer(imageryProvider)
  // 图层的背景设置透明
  arcgisImageryLayer.alpha = 1.5
  // 添加该图层服务
  imageryLayers.add(arcgisImageryLayer)
  return imageryProvider
}

// 绘制行政区域
function drawDivisionArea (viewer, imageryProvider, options = {}) {
  /*
    参数说明：
      1. viewer  cesium地图中用于构建应用程序的基本小部件
      2. options 参数配置项
        1) point 查询点的位置坐标 世界坐标系，可以通过 lnglatToCartesian 方法进行转换
        2) color 绘制区域的颜色
        3）success 绘制成功的回调
    注意：
      如果需要删除则 调用 viewer.entities.remove(entity)
      该函数返回的是 entities 的数组，删除时需要遍历删除
  */
  const { point: cartesian3 = {}, color = '#EC700C', success } = options
  // const imageryProvider = addDivisionImageryProvider(viewer)
  // const cartesian3 = lnglatToCartesian(point)
  // const cartesian3 = point
  viewer.scene.globe.depthTestAgainstTerrain = false
  getMapPickFeatures(viewer, imageryProvider, cartesian3, pickFeaturesData => {
    const geometryRings = pickFeaturesData.data.geometry.rings
    let entities = []
    geometryRings.forEach(ringItem => {
      const geometryCartesians = lnglatArrToCartesianArr(ringItem)
      let entitiesId = pickFeaturesData.properties['st_area(shape)'] + pickFeaturesData.properties['fname']
      let getByIdBox = viewer.entities.getById(entitiesId)
      if (getByIdBox) return
      let outlineEntity = viewer.entities.add({
        polyline: {
          positions: geometryCartesians,
          width: outlineWidth,
          material: Cesium.Color.fromCssColorString(color).withAlpha(0.6),
          clampToGround: true
        }
      })
      let entity = viewer.entities.add({
        id: entitiesId,
        polygon: {
          hierarchy: new Cesium.PolygonHierarchy(geometryCartesians),
          material: Cesium.Color.fromCssColorString(color).withAlpha(0.3)
          // height: 0,
          // outline: true,
          // outlineWidth: 8,
          // outlineColor: Cesium.Color.fromCssColorString(color)
        }
      })
      entities.push(outlineEntity)
      entities.push(entity)
    })
    success && success(entities)
  })
}

// 绘制返回搜索行政区域划分
function drawRangeDivisionArea (viewer, options = {}) {
  const { center = {}, distance = 0, circleColor = '#EC700C', allStreetPickeFeaturesData = [] } = options
  // 绘制园的精度
  const granularity = 0.005
  let entitiesArr = []
  viewer.scene.globe.depthTestAgainstTerrain = false
  let ellipseOutlineInner = new Cesium.EllipseOutlineGeometry({
    center,
    semiMajorAxis: distance * 1000,
    semiMinorAxis: distance * 1000,
    rotation: Cesium.Math.toRadians(0.0),
    granularity
  })
  let geometryInner = Cesium.EllipseOutlineGeometry.createGeometry(ellipseOutlineInner)
  let valuesInner = geometryInner.attributes.position.values
  let positionsInner = []
  for (let i = 0; i < valuesInner.length; i = i + 3) {
    let position = new Cesium.Cartesian3(valuesInner[i], valuesInner[i + 1], valuesInner[i + 2])
    positionsInner.push(position)
  }
  let positionsInnerLngLatArr = positionsInner.map((item, index) => {
    let cartographic = cartesianToCartographic(viewer, item)
    return [cartographic.lng, cartographic.lat]
  })
  positionsInnerLngLatArr.push(positionsInnerLngLatArr[0])
  let outlineEntity = viewer.entities.add({
    polyline: {
      positions: lnglatArrToCartesianArr(positionsInnerLngLatArr),
      width: outlineWidth,
      material: Cesium.Color.fromCssColorString(circleColor).withAlpha(0.6),
      clampToGround: true
    }
  })

  let circleEntity = viewer.entities.add({
    polygon: {
      hierarchy: new Cesium.PolygonHierarchy(positionsInner),
      material: Cesium.Color.fromCssColorString(circleColor).withAlpha(0)
      // height: 0,
      // outline: true,
      // outlineWidth: 8.0,
      // outlineColor: Cesium.Color.fromCssColorString(circleColor)
    }
  })
  entitiesArr.push(outlineEntity)
  entitiesArr.push(circleEntity)
  let poly1Arr = positionsInnerLngLatArr
  let poly1 = turf.polygon([poly1Arr])
  let entityCount = 0
  try {
    allStreetPickeFeaturesData.forEach(pickItem => {
      if (!pickItem.data.geometry) return
      const geometryRings = pickItem.data.geometry.rings
      geometryRings.forEach(ringItem => {
        let poly2Arr = ringItem
        let poly2 = turf.polygon([poly2Arr])
        let intersection = turf.intersect(poly1, poly2)
        if (!intersection) return
        const coordinates = intersection.geometry.coordinates[0]
        const geometryCartesians = lnglatArrToCartesianArr(coordinates)
        let entitiesId = pickItem.properties['st_area(shape)'] + pickItem.properties['fname']
        let getByIdBox = viewer.entities.getById(entitiesId)
        if (getByIdBox) return
        let color
        if (entityCount === 0) {
          color = '#EC700C'
        } else if (entityCount === 1) {
          color = '#2E7D9D'
        } else {
          color =
            '#' +
            Math.random()
              .toString(16)
              .substr(-6)
        }
        entityCount++
        let outlineEntity = viewer.entities.add({
          polyline: {
            positions: geometryCartesians,
            width: outlineWidth,
            material: Cesium.Color.fromCssColorString(color).withAlpha(0.6),
            clampToGround: true
          }
        })
        let polygonEntity = viewer.entities.add({
          id: entitiesId,
          polygon: {
            hierarchy: new Cesium.PolygonHierarchy(geometryCartesians),
            material: Cesium.Color.fromCssColorString(color).withAlpha(0.5)
            // height: 0,
            // outline: true,
            // outlineWidth: 8.0,
            // outlineColor: Cesium.Color.fromCssColorString(color)
          }
        })
        entitiesArr.push(outlineEntity)
        entitiesArr.push(polygonEntity)
      })
    })
  } catch (err) {
    console.error(err)
  }
  return entitiesArr
}

//  获取地图图层数据元信息  通过调用 ArcGisMapServerImageryProvider 中的 pickFeatures
function getMapPickFeatures (viewer, imageryProvider, cartesian, success) {
  /*
    参数说明：
      1. viewer  cesium地图中用于构建应用程序的基本小部件
      2. imageryProvider  提供要显示在椭球表面上的图像。
      3. cartesian 世界坐标系坐标
  */
  if (!cartesian) return
  let cartographic = Cesium.Cartographic.fromCartesian(cartesian)
  if (!cartographic) return
  let xy = new Cesium.Cartesian2()
  let alti = viewer.camera.positionCartographic.height
  let level = getLevel(alti)
  if (imageryProvider.ready) {
    xy = imageryProvider.tilingScheme.positionToTileXY(cartographic, level, xy)
    let promise = imageryProvider.pickFeatures(xy.x, xy.y, level, cartographic.longitude, cartographic.latitude)
    Cesium.when(promise, data => {
      if (data && data.length) {
        // 查询后的所有 地理行政区域 data 信息
        let pickFeaturesData
        for (let i = 0; i < data.length; i++) {
          const item = data[i]
          if (item.data.layerId === pickFeaturesLayerId) {
            pickFeaturesData = item
            break
          }
        }
        success && success(pickFeaturesData)
      }
    })
  }
}

// 将经纬度转换成Cartesian中的数组
function lnglatArrToCartesianArr (lnglatArr = []) {
  if (!lnglatArr || !lnglatArr.length) return []
  let arr = []
  for (let i = 0; i < lnglatArr.length; i++) {
    arr.push(lnglatToCartesian(lnglatArr[i]))
  }
  return arr
}

// 将经纬度转世界坐标 [101,40]
function lnglatToCartesian (lnglat) {
  if (!lnglat) return null
  return Cesium.Cartesian3.fromDegrees(lnglat[0], lnglat[1], lnglat[2] || 0)
}

// 图层点击后查询成功
function layerPickFeaturesSuccess (data = []) {
  // const geometryRings = pickFeaturesData.data.geometry.rings
  // geometryRings.forEach((ringItem) => {
  // let positionsInnerLngLatArr = positionsInner.map((item, index) => {
  //   let cartographic = cartesianToCartographic(item)
  //   return [cartographic.lng, cartographic.lat]
  // })
  // positionsInnerLngLatArr.push(positionsInnerLngLatArr[0])
  // let poly1Arr = ringItem
  // let poly2Arr = positionsInnerLngLatArr
  // var poly1 = turf.polygon([poly1Arr]);
  // var poly2 = turf.polygon([poly2Arr]);
  // var intersection = turf.intersect(poly1, poly2);
  // const coordinates = intersection.geometry.coordinates[0]
  // const geometryCartesians = lnglatArrToCartesianArr(coordinates)
  // let entitiesId = pickFeaturesData.properties['st_area(shape)'] + pickFeaturesData.properties['fname']
  // var getByIdBox = viewer.entities.getById(entitiesId);
  // if (getByIdBox) return
  // var ring = viewer.entities.add({
  //   id: entitiesId,
  //   polygon: {
  //     hierarchy: new Cesium.PolygonHierarchy(geometryCartesians),
  //     height: 0,
  //     material: Cesium.Color.RED.withAlpha(0.5),
  //     outline: true,
  //     outlineColor: Cesium.Color.BLACK
  //   }
  // });
  // });
}

// 通过世界坐标的 z 轴获取 地图服务的 level 层级
function getLevel (height) {
  if (height > 48000000) {
    return 0
  } else if (height > 24000000) {
    return 1
  } else if (height > 12000000) {
    return 2
  } else if (height > 6000000) {
    return 3
  } else if (height > 3000000) {
    return 4
  } else if (height > 1500000) {
    return 5
  } else if (height > 750000) {
    return 6
  } else if (height > 375000) {
    return 7
  } else if (height > 187500) {
    return 8
  } else if (height > 93750) {
    return 9
  } else if (height > 46875) {
    return 10
  } else if (height > 23437.5) {
    return 11
  } else if (height > 11718.75) {
    return 12
  } else if (height > 5859.38) {
    return 13
  } else if (height > 2929.69) {
    return 14
  } else if (height > 1464.84) {
    return 15
  } else if (height > 732.42) {
    return 16
  } else if (height > 366.21) {
    return 17
  } else {
    return 18
  }
}

function cartesianToCartographic (viewer, p = {}) {
  let ellipsoid = viewer.scene.globe.ellipsoid
  let cartesian3 = new Cesium.Cartesian3(p.x, p.y, p.z)
  let cartographic = ellipsoid.cartesianToCartographic(cartesian3)
  let lat = Cesium.Math.toDegrees(cartographic.latitude)
  let lng = Cesium.Math.toDegrees(cartographic.longitude)
  let height = cartographic.height
  return {
    lng,
    lat,
    height
  }
}

export { addDivisionImageryProvider, getMapPickFeatures, getLevel, drawDivisionArea, lnglatArrToCartesianArr, lnglatToCartesian, drawRangeDivisionArea }
